from selenium.webdriver.common.by import By

from qturboframe.lib.webdriver.remote.webdriver import WebDriver
from qturboframe.lib.webdriver.remote.webelement import WebElement
from qturboframe.lib.webdriver.exceptions import SeleniumError

from qturboframe.lib.report.log import logger

from .base_element import BaseElement

class Radio(BaseElement):
    '''
    Jres2.0 的单选按钮操作

    :Attributes:
     - _driver: 控件所在的当前webdriver对象
     - _elements: 单选按钮元素列表，list
     - timeout: 步骤操作的超时时间

    :Raises:
        当element_para参数类型不正确时则抛出AttributeError异常

    :Example:
     - 例1: Radio(webelement)
     - 例2: Radio({By.CLASS_NAME:'class_name','text':'文本信息'})
     - 例3: Radio({By.CLASS_NAME:'class_name','text':'文本信息'}, father=driver)
     - 例4: Radio({By.CLASS_NAME:'class_name','text':'文本信息'}, father=webelement)
    '''

    def __init__(self, element_para, father=None, timeout=5):
        if isinstance(element_para, list) and len(element_para) > 0:
            if isinstance(element_para[0], WebElement):
                self._elements = element_para
                self._driver = element_para[0]._parent
                self.timeout = timeout
            else:
                raise AttributeError('element_para参数不正确，需是WebElement的集合！')
        elif not isinstance(element_para, dict):
            raise AttributeError('element_para参数类型不正确！')
        else:
            if father is None:
                raise AttributeError('未定位元素，father参数不能为None！')
            if isinstance(father, WebDriver):
                self._driver = father
                self.timeout = timeout
            elif isinstance(father, WebElement):
                self._driver = father._parent
                self.timeout = timeout
            else:
                raise AttributeError('father参数类型不正确！')
            key_list = [By.ID, By.NAME, By.CLASS_NAME, By.TAG_NAME, By.LINK_TEXT,
                        By.PARTIAL_LINK_TEXT,By.CSS_SELECTOR, By.XPATH]
            element_by = ''
            element_value = ''
            assist = ''
            for key, value in element_para.items():
                if key in key_list:
                    element_by = key
                    element_value = value
                else:
                    assist += '{}:{},'.format(key, value)
            assist = assist.strip(',')
            self._elements = father.find_elements_by_attribute(
                element_by, element_value, assist, self.timeout)

    def set_value(self, text):
        """
        选择Jres2.0的单选按钮

        :Args:
         - inputs: 一组单选按钮控件
         - text: 选择项的文本内容
         
        :Example:
         - 例: radio.set_value("text")
        """
        for input_element in self._elements:
            radio_label = input_element.find_element_by_attribute('xpath', './parent::*', timeout=self.timeout)
            if not BaseElement(radio_label).get_text().strip():
                radio_label = radio_label.find_element_by_attribute('xpath', './parent::*', timeout=self.timeout)

            radio_text = radio_label.text.strip()
            if text == radio_text and not input_element.get_attribute('checked'):
                # radio_label.secure_click()
                BaseElement(radio_label).click()
                if not input_element.get_attribute('checked'):
                    BaseElement(input_element).click()
                break

    def verify(self):
        """
        Jres2.0的单选按钮验证是否成功

        :Args:
         - inputs: 一组单选按钮控件

        :Returns:
            验证成功返回True，验证失败返回False，无验证结果则返回None
            
        :Example:
         - 例: radio.verify()
        """
        xpath = './parent::*/parent::*/parent::div'
        div_verify = self._elements[0].find_element_by_attribute('xpath', xpath,timeout=self.timeout)
        classValue = div_verify.get_attribute('class')
        if 'u-radio-group' in classValue:
            if 'm-verify-success' in classValue:
                return True
            elif 'm-verify-error' in classValue:
                return False
            else:
                return None
        else:
            div_elements = div_verify.find_elements_by_attribute('xpath', './descendant::div',
                                                                 timeout=self.timeout)
            for div_element in div_elements:
                classValue = div_element.get_attribute('class')
                if 'u-radio-group' in classValue:
                    if 'm-verify-success' in classValue:
                        return True
                    elif 'm-verify-error' in classValue:
                        return False
                    else:
                        return None

    def get_error_info(self):
        """
        获取Jres2.0的单选按钮验证错误信息

        :Returns:
            返回错误信息
            
        :Example:
         - 例: radio.get_error_info()
        """
        errorInfo = ""
        updiv = self._elements[0].find_element_by_attribute('xpath', './parent::*/parent::*/parent::div',
                                                    timeout=self.timeout)
        classValue = updiv.get_attribute('class')
        if 'u-radio-group' in classValue:
            div_error = updiv.find_element_by_attribute(
                'xpath', './div[@class=\'m-verify-tip\']/div[@class=\'verify-tip-inner\']',
                timeout=self.timeout)
            errorInfo = div_error.text
        else:
            div_elements = updiv.find_elements_by_attribute('xpath', './descendant::div',
                                                            timeout=self.timeout)
            for div_element in div_elements:
                classValue = div_element.get_attribute('class')
                if 'u-radio-group' in classValue:
                    div_error = div_element.find_element_by_attribute(
                        'xpath', './div[@class=\'m-verify-tip\']/div[@class=\'verify-tip-inner\']',
                        timeout=self.timeout)
                    errorInfo = div_error.text
                    break
        return errorInfo

    def is_readonly_for_radio(self):
        """
        检查Jres2.0的单选按钮的选项是否只读

        :Returns:
            控件组均是只读状态则返回True，否则返回False
            
        :Example:
         - 例: radio.is_readonly_for_radio()
        """
        for inputele in self._elements:
            if not inputele.is_readonly():
                return False
        else:
            return True

    def is_default(self, value):
        """
        检查Jres2.0的单选按钮默认值

        :Args:
         - value: 待检查的选项值

        :Returns:
            匹配返回True，否则返回False
        
        :Example:
         - 例: radio.is_default("text")
        """
        for inputele in self._elements:
            status = inputele.get_attribute('checked')
            if status:
                radio_text = inputele.find_element_by_attribute('xpath:./parent::*',
                                                                timeout=self.timeout).text
                if value == radio_text:
                    return True
        else:
            logger.error('单选按钮默认值与校验值不一致！')
            return False

    def check_radio(self):
        """
        选中Jres2.0的单选框

        :Example:
         - 例1: checkbox.check_radio()
        """
        for radio in self._elements:
            if not radio.is_selected():
                try:
                    radio.click()
                except:
                    # 有的checkbox在设计中会被别的tag遮挡住，直接点击checkbox会抛出 element not visible的异常
                    # 如果抛出此异常则查找其父级元素然后点击
                    try:
                        radio.find_element_by_attribute(By.XPATH,"..").click()
                    except Exception as msg:
                        self._driver.execute_script("arguments[0].click();", radio)
